home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-05-30 | 28.0 KB | 1,619 lines | [TEXT/MPS ] |
- /*
- * Copyright © 1990 Paul Campbell, Taniwha Systems Design
- * All Rights Reserved.
- * Right to redistribute this software with the Taniwha BBS
- * is hereby granted.
- */
-
- const NULL = 0, /* nil pointer */
- USERNLEN = 30, /* length of a user name */
- TIMEOUT = 7200, /* timeout - 2 minutes - set to -1 to disable */
- MAPSIZE = 128; /* limit to the # lines in an edited file */
-
- global UserRecord[40], /* user record from user file */
- User[USERNLEN], /* user name */
- Directory[256], /* directory name of root directory for BBS system */
- Tmp[128], /* temporary array */
- Tmp1[128], /* temporary array */
- Tmp2[128], /* temporary array */
- TmpName[64], /* temporary file name */
- XUser[USERNLEN], /* other user name (used for destination of mail etc) */
- MailHdr[128], /* mail file header record */
- Subject[128], /* mail subject */
- nextc, /* next input char from edit_command() */
- col, /* editor screen column */
- line, /* editor screen line */
- lineoffset, /* index into screen of the start of the current line */
- lcount, /* editor line count */
- pos, /* editor line position */
- efree, /* editor next free block */
- elist, /* first in free edit block list */
- lmod[23], /* line has been modified */
- screen[1840], /* current screen being edited */
- ftmp, /* temp file we have open */
- fedit, /* temp file we have open for editing */
- fuser, /* user file we have open */
- MailState[6], /* mail control file */
- sysop, /* true if we are 'sysop' */
- timeout, /* system wide timeout */
- Map[MAPSIZE]; /* edit file map */
-
- /*
- * system-wide global variable use:
- *
- * A - unique number, incremented on each use
- *
- * system-wide lock uses
- *
- * 0 - user file
- * 1 - lock on mail system
- */
-
- "simple"
- {
- if (gettype() == 0) {
- timeout = -1;
- } else {
- timeout = TIMEOUT; /* set to -1 for no timeout */
- }
- for (;;) {
- setuser("");
- sysop = 0;
- getdirectory(Directory);
- setstate("Idle");
- if (!enabled())
- quit();
- connect();
- setstate("Login");
- if (!login()) {
- disconnect();
- continue;
- }
- setstate("Active");
- message_of_the_day();
- setuser(User);
- commands();
- disconnect();
- resched(); /* These recheds required for the CommToolbox to get the port back */
- resched(); /* into a sane state before trying to connect again - no one knows why :-)*/
- resched();
- }
- }
-
- do_hangup()
- {
- setuser("");
- if (TmpName[0]) {
- remove(TmpName);
- TmpName[0] = 0;
- }
- restart();
- }
-
- commands()
- {
- local c, j;
-
- for (;;) {
- stty('e', 0);
- stty('l', 0);
- if (sysop) {
- j = "C(onfig) ";
- } else {
- j = "";
- }
- printf("Main: %sP(assword) R(ead mail) S(end mail) F(iles) L(ogout) > ", j);
- c = getchartime(timeout);
- stty('e', 1);
- stty('l', 1);
- if (c == -2) {
- return;
- }
- putchar(c);
- putchar('\n');
- switch(c) {
- case 'P':
- case 'p':
- set_password(User, 0);
- break;
-
- case 'C':
- case 'c':
- if (sysop)
- config();
- break;
-
- case 'F':
- case 'f':
- do_files();
- break;
-
- case 'R':
- case 'r':
- rmail();
- break;
-
- case 'S':
- case 's':
- smail(0, 0, 0);
- break;
-
- case 'L':
- case 'l':
- return;
- }
- }
- }
-
- /*
- * rmail searches for mail to the user
- * by looking in the subdirectory 'mail:USER'
- */
-
- rmail()
- {
- local i, first, last, this, mod, c, done, x;
-
- i = get_mailstate(User, 0);
- if (i < 0) {
- printf("Mail Problem\n");
- return;
- }
- first = (MailState[0]<<8)|MailState[1];
- last = (MailState[2]<<8)|MailState[3];
- this = (MailState[4]<<8)|MailState[5];
- if (i == 0 || first > last) {
- printf("No Mail\n");
- return;
- }
- mod = 0;
- printf("First message %d, Last Message %d, Current Message %d\n",
- first, last, this);
- for (done = 0;!done;) {
- stty('e', 0);
- stty('l', 0);
- printf("Mail(%d): A(ll) D(el) R(eply) H(eader) L(ist) T(his) Q(uit) +/-> ", this);
- c = getchartime(timeout);
- stty('e', 1);
- stty('l', 1);
- if (c == -2)
- break;
- putchar(c);
- putchar('\n');
- x = 0;
- switch(c) {
- case '-':
- x = 1;
- if (this > first) {
- mod = 1;
- this--;
- }
- case '\n':
- case '\r':
- case '+':
- if (x == 0 && this < last) {
- mod = 1;
- this++;
- }
- case 'T':
- case 't':
- display_mail(this);
- break;
-
- case 'r':
- case 'R':
- reply_mail(this);
- break;
-
- case 'D':
- case 'd':
- mod = 1;
- first = delete_mail(first, this, last);
- break;
-
- case 'L':
- case 'l':
- pr_subjects(this, last);
- break;
-
- case 'A':
- case 'a':
- pr_subjects(first, last);
- break;
-
- case 'Q':
- case 'q':
- done = 1;
- break;
- }
- }
- if (mod && get_mailstate(User, 1) == 1) {
- MailState[0] = first>>8;
- MailState[1] = first;
- MailState[4] = this>>8;
- MailState[5] = this;
- set_mailstate(User, 1);
- }
- }
-
- /*
- * control file contains:
- *
- * bytes 0-1 first mail message
- * 2-3 last mail message
- * 4-6 last message read
- */
-
- get_mailstate(user, x)
- {
- local i, j;
-
- lock(1);
- sprintf(Tmp2, "%smail:%s:control", Directory, user);
- ftmp = fopen(Tmp2, "r+");
- if (ftmp) {
- i = fread(MailState, 6, 1, ftmp);
- if (i != 1 || !x) {
- fclose(ftmp);
- }
- if (i != 1)
- i = -1;
- } else {
- i = 0;
- }
- if (i != 1 || !x)
- unlock(1);
- return(i);
- }
-
- set_mailstate(user, x)
- {
- if (!x) {
- lock(1);
- sprintf(Tmp2, "%smail:%s:control", Directory, user);
- ftmp = fopen(Tmp2, "r+");
- }
- if (ftmp) {
- fseek(ftmp, 0, 0);
- fwrite(MailState, 6, 1, ftmp);
- fclose(ftmp);
- }
- if (x != 2)
- unlock(1);
- }
-
- delete_mail(first, this, last)
- {
- sprintf(Tmp2, "%smail:%s:%d", Directory, User, this);
- remove(Tmp2);
- if (this == first) {
- for (;;) {
- first++;
- if (first > last)
- break;
- sprintf(Tmp2, "%smail:%s:%d", Directory, User, first);
- ftmp = fopen(Tmp2, "r");
- if (ftmp) {
- fclose(ftmp);
- break;
- }
- }
- }
- return(first);
- }
-
- reply_mail(this)
- {
- local i, m, c;
-
- sprintf(Tmp2, "%smail:%s:%d", Directory, User, this);
- ftmp = fopen(Tmp2, "r");
- if (ftmp == NULL) {
- printf("No message %d to reply to\n", this);
- return;
- }
- for (;;) {
- c = fgetc(ftmp);
- if (c == '\'' || c == '\r' || c <= 0)
- break;
- }
- if (c == '\'') {
- for (i = 0;;i++) {
- c = fgetc(ftmp);
- if (c == '\'' || c == '\r' || c <= 0)
- break;
- XUser[i] = c;
- }
- XUser[i] = 0;
- if (i == 0)
- c = -1;
- }
- if (c == '\'') {
- for (;;) {
- c = fgetc(ftmp);
- if (c == '\'' || c == '\r' || c <= 0)
- break;
- }
- }
- if (c == '\'') {
- for (i = 0;;i++) {
- c = fgetc(ftmp);
- if (c == '\'' || c == '\r' || c <= 0)
- break;
- Subject[i] = c;
- }
- Subject[i] = 0;
- if (i == 0)
- c = -1;
- }
- if (c == '\'') {
- for (;;) {
- c = fgetc(ftmp);
- if (c == '\r' || c <= 0)
- break;
- }
- m = edit_load(ftmp);
- fclose(ftmp);
- if (Subject[0] != 'R' ||
- Subject[1] != 'e' ||
- Subject[2] != ':') {
- strcpy(Tmp1, "Re: ");
- } else {
- Tmp1[0] = 0;
- }
- strcat(Tmp1, Subject);
- strcpy(Tmp2, XUser);
- smail(Tmp2, Tmp1, m);
- } else {
- printf("Malformed file header\n");
- fclose(ftmp);
- }
- }
-
- pr_subjects(s, e)
- {
- local i, x, j, c;
-
- for (i = s, x = 0; i <= e; i++){
- sprintf(Tmp2, "%smail:%s:%d", Directory, User, i);
- ftmp = fopen(Tmp2, "r");
- if (ftmp) {
- for (j = 0;j < 126; j++) {
- Tmp[j] = c = fgetc(ftmp);
- if (c == '\r' || c < 0)
- break;
- }
- Tmp[j] = 0;
- fclose(ftmp);
- if (Tmp[0]) {
- x = 1;
- if (cantput())
- return;
- printf("%d: %s\n", i, Tmp);
- }
- }
- }
- if (x == 0)
- printf("No mail found\n");
- }
-
- display_mail(this)
- {
- sprintf(Tmp2, "%smail:%s:%d", Directory, User, this);
- ftmp = fopen(Tmp2, "r");
- if (ftmp == NULL) {
- printf("No mail %d (deleted)\n", this);
- return;
- }
- file_cat(ftmp);
- fclose(ftmp);
- }
-
- /*
- * send mail
- */
-
- smail(to, subject, xf)
- {
- local m, i, x, c, s, done;
-
- if (to == 0) {
- printf("To> ");
- if (readlinetime(XUser, 40, timeout) != 0)
- return;
- } else {
- strcpy(XUser, to);
- }
- if (XUser[0] == 0)
- return;
- if (subject == 0) {
- printf("Subject> ");
- if (readlinetime(Subject, 80, timeout) != 0)
- return;
- } else {
- strcpy(Subject, subject);
- }
- if (xf) {
- m = xf;
- } else {
- m = edit_empty(1);
- if (m == NULL) {
- printf("Cannot open temporary file for editing\n");
- return;
- }
- }
- done = 0;
- for (c = 'e';;) {
- switch(c) {
- case 'h':
- case 'H':
- printf("To> ");
- if (readlinetime(XUser, 40, timeout) != 0) {
- done = 1;
- break;
- }
- printf("Subject> ");
- if (readlinetime(Subject, 80, timeout) != 0) {
- done = 1;
- break;
- }
- break;
-
- case 'e':
- case 'E':
- edit(m);
- break;
-
- case 's':
- case 'S':
- i = 0;
- x = 0;
- s = 0;
- done = 1;
- for (;c!= 0;i++) {
- c = XUser[i];
- if (s == 0) {
- if (c == 0)
- break;
- if (c != ' ' && c != ',') {
- Tmp1[x++] = c;
- s = 1;
- }
- } else {
- if (c == 0 || c == ',') {
- while (x > 0 && Tmp1[x-1] == ' ')
- x--;
- if (x != 0) {
- Tmp1[x] = 0;
- if (send_mail(Tmp1, Subject, m)) {
- printf("Can't send mail to %s\n", Tmp1);
- done = 0;
- } else {
- printf("Sent to %s\n", Tmp1);
- }
- x = 0;
- }
- s = 0;
- } else {
- Tmp1[x++] = c;
- }
- }
- }
- break;
-
- case 'a':
- case 'A':
- done = 1;
- break;
- }
- if (done)
- break;
- stty('e', 0);
- stty('l', 0);
- printf("Send Mail: A(bort) E(dit mail) H(eader) S(end mail) > ");
- c = getchartime(timeout);
- stty('e', 1);
- stty('l', 1);
- if (c == -2)
- break;
- putchar(c);
- putchar('\n');
- }
- fclose(m);
- if (m == fedit) {
- if (TmpName[0]) {
- remove(TmpName);
- TmpName[0] = 0;
- }
- }
-
- }
-
- send_mail(to, subject, f)
- {
- local last, i;
-
- i = get_mailstate(to, 1);
- if (i != 1) {
- lock(1);
- ftmp = fopen(Tmp2, "w+");
- if (ftmp == NULL) {
- unlock(1);
- return(1);
- }
- last = -1;
- MailState[4] = 0;
- MailState[5] = 1;
- } else {
- last = (MailState[2]<<8)|MailState[3];
- }
- if (last == -1) { /* no mail at all */
- MailState[1] = 1;
- MailState[3] = 0;
- last = 1;
- } else {
- last++;
- MailState[2] = last>>8;
- MailState[3] = last;
- }
- set_mailstate(to, 2);
- sprintf(Tmp2, "%smail:%s:%d", Directory, to, last);
- ftmp = fopen(Tmp2, "w+");
- if (ftmp == NULL) {
- unlock(1);
- return(1);
- }
- fprintf(ftmp, "From: '%s' Subject: '%s'\r", User, subject);
- edit_save(f, ftmp);
- fclose(ftmp);
- unlock(1);
- return(0);
- }
-
- /*
- * This routine logs a user on, the user file record will be
- * in global array 'E'
- *
- */
-
- login()
- {
- local c, done, try, passwd;
-
- done = 0;
- for (try = 0;try < 3;try++) {
- switch(try) {
- case 0:
- stty('s', 2400);
- break;
- case 1:
- stty('s', 1200);
- break;
- case 2:
- stty('s', 300);
- break;
- }
- for (;;) {
- printf("\nLogin to BBS:");
- if (readlinetime(User, 40, timeout) != 0)
- break;
- if (User[0] == 0)
- continue;
- passwd = get_password("Password:", 1);
- if (passwd == 0)
- break;
- if (userinfo(User, passwd, 0, 0, 0)) {
- sysop = strcmp("sysop", User) == 0;
- return(1);
- }
- }
- }
- return(0);
- }
-
- /*
- * edit - edits a file (be it empty or otherwise
- *
- * a VERY simple text editor,
- *
- * Commands:
- * <char> insert a printable char
- * DEL delete the letter to the left of the cursor (if there is one)
- * or join 2 lines
- * CR insert a new line (split an existing one)
- * ESC [ A cursor up
- * ESC O A
- * ESC A
- * ESC [ B cursor down
- * ESC O B
- * ESC B
- * ESC [ C cursor left
- * ESC O C
- * ESC C
- * ESC [ D cursor right
- * ESC O D
- * ESC D
- * ^L refresh
- * ^D Quit
- */
-
- edit(f)
- {
- local cmd, i, len, b, x, k, j, xcol, tab, wait;
-
- pos = 0;
- col = 0;
- line = 0;
- xcol = 0;
- tab = 0;
- wait = 0;
- stty('e', 0);
- stty('l', 0);
- x = 0;
- for (i = 0; i < 23; i++) {
- if (i < lcount) {
- fseek(f, Map[i]*80, 0);
- fread(&screen[x], 80, 1, f);
- } else {
- screen[x] = 0;
- }
- lmod[i] = 0;
- x += 80;
- }
- lineoffset = 0;
- len = strlen(&screen[0]);
- refresh(f);
- for (;;) {
- if (tab > 0) {
- i = 0;
- nextc = ' ';
- tab--;
- } else {
- i = edit_command();
- if (wait) {
- refresh();
- wait = 0;
- continue;
- }
- }
- switch(i) {
- case 0: /* insert nextc */
- if (len >= 79) {
- putchar(7);
- break;
- }
- xcol = 0;
- lmod[line] = lmod[line]|1;
- if (col == len) {
- screen[lineoffset+col] = nextc;
- col++;
- len++;
- screen[lineoffset+col] = 0;
- putchar(nextc);
- break;
- }
- for (i = (lineoffset+len);i > (lineoffset+col);i--)
- screen[i] = screen[i-1];
- screen[lineoffset+col] = nextc;
- len++;
- screen[lineoffset+len] = 0;
- putstr(&screen[lineoffset+col]);
- col++;
- goto(col, line);
- break;
-
- case 1: /* up cursor */
- if (line > 0) {
- line--;
- lineoffset -= 80;
- len = strlen(&screen[lineoffset]);
- } else {
- if (pos == 0)
- break;
- edit_purge(f, 22, 22);
- for (i = 22, j=(22*80);i > 0; i--, j -= 80) {
- lmod[i] = lmod[i-1];
- strcpy(&screen[j], &screen[j-80]);
- }
- scroll_down(0, 22);
- goto(0,0);
- fseek(f, Map[pos-1]*80, 0);
- fread(&screen[0], 80, 1, f);
- putstr(&screen[0]);
- lmod[0] = 0;
- }
- pos--;
- if (xcol && col < xcol)
- col = xcol;
- if (col > len) {
- xcol = col;
- col = len;
- }
- goto(col, line);
- break;
-
- case 2:
- if (pos == (lcount-1))
- break;
- if (line < 22) {
- line++;
- lineoffset += 80;
- len = strlen(&screen[lineoffset]);
- } else {
- edit_purge(f, 0, 0);
- for (i = 0, j=0;i < 22; i++, j += 80) {
- lmod[i] = lmod[i+1];
- strcpy(&screen[j], &screen[j+80]);
- }
- scroll_up(0, 22);
- goto(0,22);
- fseek(f, Map[pos+1]*80, 0);
- x=fread(&screen[lineoffset], 80, 1, f);
- putstr(&screen[lineoffset]);
- lmod[22] = 0;
- }
- pos++;
- if (xcol && col < xcol)
- col = xcol;
- if (col > len) {
- xcol = col;
- col = len;
- }
- goto(col, line);
- break;
-
- case 3:
- if (col < len) {
- col++;
- xcol = 0;
- }
- goto(col, line);
- break;
-
- case 4:
- if (col > 0) {
- col--;
- xcol = 0;
- }
- goto(col, line);
- break;
-
- case 5:
- refresh(f);
- break;
-
- case 6:
- clear();
- edit_purge(f, 0, 22);
- stty('e', 1);
- stty('l', 1);
- return;
-
- case 7:
- if (col == 0) {
- if (pos == 0)
- break;
- if (line == 0) {
- fseek(f, Map[pos-1]*80, 0);
- fread(Tmp, 80, 1, f);
- i = strlen(Tmp);
- if ((i + len) > 79) { /* too long */
- putchar('\007');
- break;
- }
- strcpy(&Tmp[i], &screen[0]);
- strcpy(&screen[0], Tmp);
- len += i;
- edit_freeblock(Map[pos]);
- col = i;
- lcount--;
- for (i = pos; i < lcount; i++)
- Map[i] = Map[i+1];
- pos--;
- goto(0, 0);
- putstr(&screen[0]);
- } else {
- i = strlen(&screen[lineoffset-80]);
- if ((i+len) > 79) {
- putchar('\007');
- break;
- }
- col = i;
- goto(col, line-1);
- putstr(&screen[lineoffset]);
- strcpy(&screen[lineoffset-80+i], &screen[lineoffset]);
- for (i = line, j = pos, k = lineoffset; i < 22; i++, j++, k += 80) {
- if (j > lcount)
- break;
- strcpy(&screen[k], &screen[k+80]);
- }
- len += col;
- edit_freeblock(Map[pos]);
- lcount--;
- for (i = pos; i < lcount; i++)
- Map[i] = Map[i+1];
- for (i = line; i < 22; i++)
- lmod[i] = lmod[i+1];
- pos--;
- scroll_up(line, 22);
- i = pos-line+22;
- if (i >= lcount) {
- goto(0, 22);
- putchar('~');
- screen[80*22] = 0;
- } else {
- fseek(f, Map[i]*80, 0);
- fread(&screen[80*22], 80, 1, f);
- goto(0, 22);
- putstr(&screen[80*22]);
- lmod[22] = 0;
- }
- line--;
- lineoffset -= 80;
- }
- goto(col, line);
- lmod[line] = lmod[line]|1;
- break;
- }
- xcol = 0;
- col--;
- len--;
- lmod[line] = lmod[line]|1;
- if (col == len) {
- screen[lineoffset+len] = 0;
- goto(col, line);
- putchar(' ');
- goto(col, line);
- break;
- }
- goto(col, line);
- putstr(&screen[lineoffset+col+1]);
- putchar(' ');
- goto(col, line);
- for (i = (lineoffset+col); i < (lineoffset+len); i++)
- screen[i] = screen[i+1];
- screen[lineoffset+len] = 0;
- break;
-
- case 8:
- b = edit_newblock(f, 0);
- xcol = 0;
- if (col != len)
- erase_eol();
- if (line == 22) {
- edit_purge(f, 0, 0);
- x = screen[lineoffset+col];
- screen[lineoffset+col] = 0;
- for (i = 0, j = 0;i < 22; i++, j += 80) {
- lmod[i] = lmod[i+1];
- strcpy(&screen[j], &screen[j+80]);
- }
- screen[lineoffset+col] = x;
- strcpy(&screen[lineoffset], &screen[lineoffset+col]);
- if (len != col)
- lmod[21] = lmod[21]|1;
- } else {
- edit_purge(f, 22, 22);
- for (i = 22, j=(22*80);i > (line+1); i--, j -= 80) {
- lmod[i] = lmod[i-1];
- strcpy(&screen[j], &screen[j-80]);
- }
- strcpy(&screen[lineoffset+80], &screen[lineoffset+col]);
- screen[lineoffset+col] = 0;
- if (len != col)
- lmod[line] = lmod[line]|1;
- }
- len -= col;
- col = 0;
- pos++;
- for (i = lcount; i > pos; i--)
- Map[i] = Map[i-1];
- lcount++;
- Map[pos] = b;
- if (line == 22) { /* scroll everything up */
- scroll_up(0, 22);
- } else {
- line++;
- lineoffset += 80;
- scroll_down(line, 22);
- }
- lmod[line] = lmod[line]|1;
- goto(0, line);
- if (col != len) {
- putstr(&screen[lineoffset]);
- goto(0, line);
- }
- break;
-
- case 9:
- i = col&7;
- if (i == 0) {
- tab = 8;
- } else {
- tab = 8 - i;
- }
- break;
-
- case 10:
- clear(); putstr("Taniwha BBS Editor");
- goto(0, 1); putstr("==================");
- goto(0, 3); putstr("Type any character to insert it at the cursor");
- goto(0, 5); putstr("Type type the 'Delete' or 'Backspace' key to delete the character");
- goto(0, 6); putstr(" to the left off the cursor, or, if the cursor is at the left");
- goto(0, 7); putstr(" of the screen to join the current line to the previous one.");
- goto(0, 9); putstr("Type 'return' to insert a new line at the cursor");
- goto(0, 11); putstr("Use the arrow keys to move on the screen (or 'ESC' A/B/C/D to");
- goto(0, 12); putstr(" move up/down/left right)");
- goto(0, 14); putstr("Type Ctrl-D (hold down the 'Control' key and type D)");
- goto(0, 15); putstr(" to exit the editor)");
- goto(0, 22); putstr("Type any character to continue");
- wait = 1;
- break;
- }
- }
- }
-
- /*
- * write back the changed lines to the backing store
- */
-
- edit_purge(f, s, e)
- {
- local i, x;
-
- for (i = s; i <= e; i++)
- if (lmod[i]) {
- x = pos-line+i;
- if (x >= lcount)
- break;
- fseek(f, Map[x]*80, 0);
- fwrite(&screen[i*80], 80, 1, f);
- }
- }
-
- /*
- * append the edit file f to f2
- */
-
- edit_save(f, f2)
- {
- local i, j;
-
- for (i = 0; i < lcount; i++) {
- fseek(f, Map[i]*80, 0);
- fread(Tmp, 80, 1, f);
- j = strlen(Tmp);
- Tmp[j] = '\r';
- fwrite(Tmp, j+1, 1, f2);
- }
- }
-
- /*
- * make a new edit file containing the contents of the rest of file f
- */
-
- edit_load(f)
- {
- local m;
-
- m = edit_empty(0);
- if (m == NULL) {
- return(NULL);
- }
- edit_append(m, f);
- return(m);
- }
-
- /*
- * load the rest of file f into edit file m
- */
-
- edit_append(m, f)
- {
- local l, x, i, c;
-
- l = 0;
- x = 0;
- i = 0;
- for (;;) {
- if (l == i) {
- l = fread(Tmp2, 1, 128, f);
- if (l <= 0)
- break;
- i = 0;
- }
- c = Tmp2[i];
- i++;
- if (c == '\r') {
- Tmp1[x] = 0;
- x = 0;
- Map[lcount] = edit_newblock(m, 1);
- fseek(m, 80*Map[lcount], 0);
- fwrite(Tmp1, 80, 1, m);
- lcount++;
- if (lcount == MAPSIZE)
- break;
- } else {
- if (x < 79) {
- Tmp1[x] = c;
- x++;
- }
- }
- }
- if (x > 0 || lcount == 0) {
- Tmp1[x] = 0;
- Map[lcount] = edit_newblock(m, 1);
- fseek(m, 80*Map[lcount], 0);
- fwrite(Tmp1, 80, 1, m);
- lcount++;
- }
- }
-
- /*
- * make a temporary edit file
- */
-
- edit_empty(add)
- {
- local i;
-
- A++;
- i = A; /* use global variable to get unique file name */
- sprintf(TmpName, "%stmp:%d", Directory, i);
- fedit = fopen(TmpName, "w+");
- if (fedit == NULL)
- return(NULL);
- elist = 0;
- efree = 0;
- if (add) {
- Map[0] = edit_newblock(fedit, 1);
- Tmp[0] = 0;
- fseek(fedit, Map[0]*80, 0);
- fwrite(Tmp, 80, 1, fedit); /* add an empty line */
- lcount = 1;
- } else {
- lcount = 0;
- }
- return(fedit);
- }
-
- /*
- * what follows are for a vt100, change to suit your own terminal(s)
- */
-
- /*
- * scroll up 1 line the screen between lines t(op) and b(ottom)
- */
-
- scroll_up(t, b)
- {
- set_scroll(t, b);
- goto(0, b);
- putchar('\n');
- clear_scroll();
- }
-
- /*
- * scroll down 1 line the screen between lines t(op) and b(ottom)
- */
-
- scroll_down(t, b)
- {
- set_scroll(t, b);
- goto(0, t);
- putstr("\033M");
- clear_scroll();
- }
-
- /*
- * put the screen into scroll mode between lines t and b
- */
-
- set_scroll(t, b)
- {
- printf("\033[%d;%dr", t+1,b+1);
- }
-
- /*
- * clear scrolling region
- */
-
- clear_scroll()
- {
- putstr("\033[r");
- }
-
- /*
- * erase the line from the cursor to the end
- */
-
- erase_eol()
- {
- putstr("\033[K");
- }
-
- /*
- * clear the whole screen
- */
-
- clear()
- {
- putstr("\033[H\033[J");
- }
-
- /*
- * go to a particular screen location
- */
-
- goto(x, y)
- {
- printf("\033[%d;%dH",y+1,x+1);
- }
-
- /*
- * redraw the screen
- */
-
- refresh(f)
- {
- local i, j;
-
- clear_scroll();
- clear();
- for (i = 0, j = 0; i < 23; i++, j += 80) {
- goto(0, i);
- if ((pos-line+i) < lcount) {
- putstr(&screen[j]);
- } else {
- putchar('~');
- }
- }
- goto(0, 23);
- putstr("^D - quit, DEL delete, ^L refresh - use arrows to move, <ESC> ? for help");
- goto(col, line);
- }
-
- cantput()
- {
- local x, y;
-
- y = 1;
- resched();
- resched();
- x = peekc();
- for (;;) {
- if (y && x < 0)
- return(0);
- x = getchar();
- if (x == 's' || x == 'S' || x == 0x13) {
- x = getchar();
- y = 0;
- continue;
- }
- if (x == 'q' || x == 'Q' || x == 0x11)
- return(0);
- if (x == 3 || x == 'k' || x == 'K')
- return(1);
- }
- }
-
- /*
- * allocate an 80 byte block from the file
- */
-
- edit_newblock(f, a)
- {
- local x;
-
- if (elist) {
- x = elist;
- fseek(f, elist*80, 0);
- fread(Tmp, 80, 1, f);
- elist = Tmp[0];
- return(x);
- }
- x = efree;
- if (a == 0) {
- fseek(f, efree*80, 0);
- fwrite(Tmp, 80, 1, f);
- }
- efree++;
- return(x);
- }
-
- /*
- * free a block from the file
- */
-
- edit_freeblock(f, x)
- {
- local x;
-
- if (x == (efree-1)) {
- efree = x;
- return;
- }
- Tmp[0] = elist;
- fseek(f, x*80, 0);
- fwrite(Tmp, 80, 1, f);
- elist = x;
- }
-
- /*
- * edit commands, returned in d:
- *
- * 0 - insert char
- * 1 - up
- * 2 - down
- * 3 - left
- * 4 - right
- * 5 - refresh
- * 6 - quit
- * 7 - delete
- * 8 - new line
- * 9 - tab
- * 10 - help
- */
-
- edit_command()
- {
- local d;
-
- d = 0;
- for (;;) {
- nextc = getchartime(timeout);
- if (nextc == -2)
- return(6);
- switch(d) {
- case 0:
- if (nextc >= ' ' && nextc < 0x7f)
- return(0);
- if (nextc == '\033') {
- d = 1;
- continue;
- }
- if (nextc == 9) {
- return(9);
- }
- if (nextc == 0x7f || nextc == 8) {
- return(7);
- }
- if (nextc == 13 || nextc == 11)
- return(8);
- if (nextc == 4)
- return(6);
- if (nextc == 12)
- return(5);
- break;
-
- case 1:
- if (nextc == '?')
- return(10);
- if (nextc == 'O' || nextc == '[') {
- d = 2;
- continue;
- }
- case 2:
- if (nextc >= 'A' && nextc <= 'D')
- return(nextc - 'A' + 1);
- if (nextc >= 'a' && nextc <= 'd')
- return(nextc - 'a' + 1);
- d = 0;
- break;
- }
- }
- }
-
- /*
- * This routine takes the user name in global array A
- * and a 16-bit hashed password in global variable a
- * it locks updates between multiple users.
- *
- * If add is set then an entry is also added
- *
- * If del is set and a==0 or a==the password in the entry
- * the entry is deleted
- *
- * If pass is set then set the password
- *
- */
-
- userinfo(name, passwd, add, del, pass)
- {
- local r, i, c;
-
- passwd &= 0xffff;
- r = 0;
- i = -1;
- sprintf(Tmp, "%scontrol:User File", Directory);
- lock(0); /* lock the user data base */
- fuser = fopen(Tmp, "r+");
- if (fuser == NULL) {
- fuser = fopen(Tmp, "w");
- if (fuser == NULL) {
- sprintf(Tmp, "%scontrol", Directory);
- mkdir(Tmp);
- sprintf(Tmp, "%scontrol:User File", Directory);
- fuser = fopen(Tmp, "w");
- if (fuser == NULL) {
- unlock(0);
- return(0);
- }
- }
- strcpy(Tmp, "sysop");
- Tmp[38] = 0;
- Tmp[39] = 1;
- fwrite(Tmp, 40, 1, fuser);
- strcpy(Tmp, "guest");
- Tmp[38] = 0;
- Tmp[39] = 1;
- fwrite(Tmp, 40, 1, fuser);
- fclose(fuser);
- sprintf(Tmp, "%smail", Directory);
- mkdir(Tmp);
- sprintf(Tmp, "%smail:sysop", Directory);
- mkdir(Tmp);
- sprintf(Tmp, "%smail:guest", Directory);
- mkdir(Tmp);
- sprintf(Tmp, "%scontrol:User File", Directory);
- fuser = fopen(Tmp, "r+");
- }
- if (fuser) {
- for (;;) {
- i = fread(Tmp, 40, 1, fuser);
- if (i <= 0) {
- if (add) {
- name[38] = passwd>>8;
- name[39] = passwd;
- if (r != 0) {
- fseek(fuser, r-40, 0);
- } else {
- fseek(fuser, 0, 2);
- }
- fwrite(name, 40, 1, fuser);
- memcpy(UserRecord, name, 40);
- r = 1;
- } else {
- r = 0;
- }
- fclose(fuser);
- unlock(0);
- return(r);
- }
- if (Tmp[0] == 0) {
- if (r == 0)
- r = ftell(fuser);
- } else
- if (strcmp(Tmp, name) == 0) {
- c = (Tmp[38]<<8)|Tmp[39];
- if (pass || (del && (passwd == 0 || passwd == c || sysop))) {
- if (del) {
- Tmp[0] = 0;
- } else
- if (pass) {
- Tmp[38] = passwd>>8;
- Tmp[39] = passwd;
- }
- fseek(fuser, -40, 1);
- fwrite(Tmp, 40, 1, fuser);
- }
- memcpy(UserRecord, Tmp, 40);
- fclose(fuser);
- unlock(0);
- return(pass || passwd == c || passwd == 0 || sysop);
- }
- }
- }
- unlock(0);
- return(0);
- }
-
- /*
- * print the contents of a file
- */
-
- file_cat(f)
- {
- local i, l;
-
- for (;;) {
- if (cantput())
- break;
- l = fread(Tmp, 1, 128, f);
- if (l <= 0)
- break;
- for (i = 0; i < l; i++)
- if (Tmp[i] == '\r')
- Tmp[i] = '\n';
- putline(Tmp, l);
- }
- }
-
- /*
- * print 'message of the day'
- */
-
- message_of_the_day()
- {
- sprintf(Tmp2, "%smessage", Directory);
- ftmp = fopen(Tmp2, "r");
- if (ftmp) {
- file_cat(ftmp);
- fclose(ftmp);
- }
- }
-
-
- config()
- {
- local c;
-
- for (;;) {
- stty('e', 0);
- stty('l', 0);
- printf("Config: A(dd user) D(elete user) P(assword) Q(uit) > ");
- c = getchar();
- stty('e', 1);
- stty('l', 1);
- putchar(c);
- putchar('\n');
- switch(c) {
- case 'A':
- case 'a':
- printf("Add User: ");
- readline(XUser, 40);
- set_password(XUser, 1);
- sprintf(Tmp, "%smail:%s", Directory, XUser);
- mkdir(Tmp);
- break;
-
- case 'D':
- case 'd':
- printf("Delete User: ");
- readline(XUser, 40);
- if (!userinfo(XUser, 0, 0, 1, 0))
- printf("Invalid user '%s'\n", XUser);
- break;
-
- case 'P':
- case 'p':
- printf("Password User: ");
- readline(XUser, 40);
- set_password(XUser, 0);
- break;
-
- case 'Q':
- case 'q':
- return;
- }
- }
- }
-
- set_password(user, add)
- {
- local i1, i2;
- i1 = get_password("New Password: ", 0);
- i2 = get_password("Re-enter new Password: ", 0);
- if (i1 != i2) {
- printf("Passwords not the same, try again\n");
- return;
- }
- if (!userinfo(user, i1, add, 0, 1))
- printf("Invalid user '%s'\n", user);
- }
-
- get_password(prompt, t)
- {
- local passwd, done, c;
-
- done = 0;
- stty('e', 0);
- stty('l', 0);
- putstr(prompt);
- passwd = 0;
- for (;;) {
- c = getchartime(timeout);
- if (c == -2)
- break;
- if (t && (c&0x80 || c == 0))
- break;
- if (c == '\n' || c == '\r') {
- done = 1;
- break;
- }
- passwd = passwd + (c<<1);
- putchar('.');
- }
- stty('e', 1);
- stty('l', 1);
- putchar('\n');
- if (t && !done)
- return(0);
- if (passwd == 0)
- passwd = 1;
- return(passwd);
- }
-
- /*
- * file upload/download area
- */
-
- do_files()
- {
- local c, t, f;
-
- f = "XMODEM";
- t = "Method StraightXMODEM Option Standard Creator \"ttxt\" Timeout 5 Retry 5 RemoteName False";
-
- for (;;) {
- stty('e', 0);
- stty('l', 0);
- printf("Files: D(ownload) U(pload) L(ist) Q(uit) > ");
- c = getchartime(timeout);
- stty('e', 1);
- stty('l', 1);
- if (c == -2)
- return;
- putchar(c);
- putchar('\n');
- switch(c) {
- case 'D':
- case 'd':
- printf("File> ");
- if (readlinetime(Tmp, 40, timeout) != 0)
- continue;
- if (Tmp[0] == 0)
- continue;
- sprintf(Tmp2, "%sfiles:%s", Directory, Tmp);
- ftmp = fopen(Tmp2, "r");
- if (ftmp == NULL) {
- printf("File %s doesn't exist\n", Tmp);
- break;
- }
- fclose(ftmp);
- if (ft_new(f, t)) {
- printf("Transfer Failed\n");
- break;
- }
- sprintf(Tmp2, "%sfiles", Directory);
- if (ft_start(Tmp2, Tmp, 1))
- printf("Transfer Failed\n");
- ft_dispose();
- break;
-
- case 'U':
- case 'u':
- printf("File> ");
- if (readlinetime(Tmp, 40, timeout) != 0)
- continue;
- if (Tmp[0] == 0)
- continue;
- sprintf(Tmp2, "%sfiles:%s", Directory, Tmp);
- ftmp = fopen(Tmp2, "r");
- if (ftmp) {
- fclose(ftmp);
- printf("File %s already exists\n", Tmp);
- break;
- }
- if (ft_new(f, t)) {
- printf("Transfer Failed\n");
- break;
- }
- sprintf(Tmp2, "%sfiles", Directory);
- if (ft_start(Tmp2, Tmp, 0))
- printf("Transfer Failed\n");
- ft_dispose();
- break;
-
- case 'L':
- case 'l':
- break;
-
- case 'Q':
- case 'q':
- return;
- }
- }
- }
-
-